import time, openpyxl, os, datetime
from selenium.webdriver.common.keys import Keys
from DrissionPage import ChromiumPage


def convert_num(s):
    try:
        if "万+" in s:
            num_str = s.replace("万+", "")
            num = float(num_str)
            return int(num * 10000)
        else:
            return int(s)
    except Exception as e:
        print(f"数字转换错误: {s}, 错误: {e}")
        return 0


fanye = int(input("请输入按键次数(500次约2000条数据)："))

# 记录程序开始时间
start_time = time.time()
# 创建页面对象
page = ChromiumPage()

try:
    # 打开登录页面
    page.get("https://channels.weixin.qq.com/login.html")
    # page.get('https://channels.weixin.qq.com/platform/commodity/pool')

    # 检测网页变化，当跳转至客服页面后自动向下执行代码
    while True:
        if "platform" in page.url:
            break

    print("登录成功")

    # 登录后跳转商品页，并选取销量1k以上条件
    page.get('https://channels.weixin.qq.com/platform/commodity/pool')
    time.sleep(8)

    # wujie-app 包含 Shadow DOM，需要进入节点后才能选择按钮
    # 定位 wujie-app 元素
    wujie_app = page.ele('xpath://*[@id="container-wrap"]/div[2]/div/wujie-app')

    try:
        shadow_root = wujie_app.shadow_root
        button_yxl = shadow_root.ele('xpath://div[3]/div/div[3]/div[3]/div[4]/dl/dt')

        button_yxl.click()  # 点击按钮
        time.sleep(0.5)

    except Exception as e:
        print(f"定位失败: {e}")

    try:
        shadow_root = wujie_app.shadow_root
        button_1k = shadow_root.ele('xpath:///div[3]/div/div[3]/div[3]/div[4]/dl/div[1]/ul/li[4]/div/div/span[1]')

        button_1k.click()  # 点击按钮
        time.sleep(0.5)

    except Exception as e:
        print(f"定位失败: {e}")

    # 智能滚动，直到内容不再更新
    prev_height = 0  # 页面高度
    scroll_attempts = 0  # 尝试次数
    max_attempts = 1  # 连续 5 次高度不变时认为已加载全部内容

    print("开始滚动页面加载数据...")


    def advanced_scroll(page, max_attempts=5, timeout=10):
        """高级滚动函数，支持多种滚动策略"""
        prev_height = page.run_js('return document.body.scrollHeight')
        scroll_attempts = 0

        print("开始高级滚动加载数据...")

        while scroll_attempts < max_attempts:
            print(f"尝试滚动 {scroll_attempts + 1}/{max_attempts} ")
            # 添加额外延迟，给页面更多时间响应
            time.sleep(1)

            # 模拟按下下方向键滚动页面
            body = page.ele('tag:body')
            # 模拟点击页面，必须存在，否则无法移动焦点进行滚动
            body.click()
            for _ in range(fanye):
                body.input(Keys.ARROW_DOWN)

            # DrissionPage页面内置滚动方法，无法生效
            # page.scroll.to_bottom()

            # 等待页面加载
            try:
                time.load_start(timeout=timeout)
                time.load_start(timeout=timeout)
            except:
                print("等待超时，继续尝试...")

            # 获取当前页面高度
            current_height = page.run_js('return document.body.scrollHeight')

            # print(f"当前页面高度: {current_height}, 上次高度: {prev_height}")

            if current_height == prev_height:
                scroll_attempts += 1
                print(f"页面高度未变化，尝试次数: {scroll_attempts}")
            else:
                scroll_attempts = 0
                prev_height = current_height
                print("页面高度增加，继续滚动...")

        print(f"滚动完成，共尝试 {scroll_attempts} 次")
        return prev_height


    # 使用高级滚动函数
    advanced_scroll(page, max_attempts=10, timeout=5)

    print("页面滚动完成")

    # 处理shadow-root并获取商品列表
    print("正在查找商品元素...")
    app = page.ele('css:wujie-app.wujie_iframe', timeout=20)
    commodity_list = app.shadow_root.eles('css:div.commodity-container')

    # if not commodity_list:
    #     raise Exception("未找到商品容器元素")
    app = page.ele('css:wujie-app.wujie_iframe', timeout=20)

    if not app.shadow_root:
        raise Exception("无法访问应用的 shadow root")

    # 尝试使用不同的选择策略查找所有商品容器
    commodity_list = []

    # 策略1：直接查找
    container = app.shadow_root.ele('css:div.commodity-container')
    commodity_list = container.eles('css:div.commodity-wrap')

    # 策略2：如果直接查找失败，尝试递归查找所有子元素
    # if not commodity_list:
    #     print("尝试递归查找商品容器...")
    #
    #     def find_commodity_containers(element):
    #         containers = []
    #
    #         # 只对元素对象检查类名，跳过 ShadowRoot 对象
    #         if hasattr(element, 'attr'):  # 检查是否有 attr 方法
    #             class_name = element.attr('class')  # 只传入一个参数
    #             if class_name and 'commodity-container' in class_name:
    #                 containers.append(element)
    #
    #         # 查找当前元素的所有子元素
    #         children = []
    #         if hasattr(element, 'eles'):
    #             children = element.eles('css:*')
    #
    #         # 递归检查每个子元素
    #         for child in children:
    #             # 检查子元素是否有shadow root
    #             if child.shadow_root:
    #                 shadow_children = child.shadow_root.eles('css:*')
    #                 for shadow_child in shadow_children:
    #                     containers.extend(find_commodity_containers(shadow_child))
    #             else:
    #                 containers.extend(find_commodity_containers(child))
    #
    #         return containers
    #
    #     从根shadow root开始递归查找
    #     commodity_list = find_commodity_containers(app.shadow_root)

    if not commodity_list:
        raise Exception("未找到任何商品容器元素")

    print(f"共找到 {len(commodity_list)} 个商品容器")

    # 创建Excel工作簿
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.append(['产品', '销量', '售价', '店铺', '店铺分', '类目', '时间'])
    today = datetime.date.today()

    # 提取数据
    total_items = 0
    print("开始提取商品数据...")

    for item in commodity_list:
        try:
            # 查找所有需要的元素
            name_ele_list = item.eles('css:div.commodity-title', timeout=0.3)
            shop_ele_list = item.eles('css:div.platform-name', timeout=0.3)
            price_ele_list = item.eles('css:div.money', timeout=0.3)
            sale_ele_list = item.eles('css:div.sales.label', timeout=0.3)
            score_ele_list = item.eles('css:div.rank.high', timeout=0.3)

            # 从列表中获取第一个元素并提取文本，处理可能的空列表情况
            name = name_ele_list[0].text if name_ele_list else "未知名称"
            shop = shop_ele_list[0].text if shop_ele_list else "未知店铺"
            price = price_ele_list[0].text.replace('¥', '') if price_ele_list else "0"
            sale_text = sale_ele_list[0].text.replace('月销', '') if sale_ele_list else "0"
            sale_num = convert_num(sale_text)
            score = score_ele_list[0].text.replace('高', '') if score_ele_list else "0"

            # 添加到Excel
            data = [name, sale_num, price, shop, score, '全部', today]
            ws.append(data)
            total_items += 1

            print(f'已提取: {name} - 销量:{sale_num}')

        except Exception as e:
            print(f"提取商品数据时出错: {e}")
            continue

    # 确保保存目录存在
    save_dir = r'E:\测试\视频号'
    os.makedirs(save_dir, exist_ok=True)

    # 保存Excel文件
    file_path = os.path.join(save_dir, f'销量1K以上{today}数据.xlsx')
    wb.save(file_path)

    print(f"数据已成功保存到: {file_path}")
    print(f"共提取 {total_items} 条商品数据")

except Exception as e:
    print(f"程序执行出错: {e}")
finally:
    # 确保浏览器总是会关闭
    page.quit()
    print("浏览器已关闭")

# 记录结束时间
end_time = time.time()
duration = end_time - start_time

print(f"程序运行耗时: {duration:.2f} 秒")
